package airportCoordination;

import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.util.concurrent.BlockingQueue;
import org.json.JSONObject;

public class IncomingHandler implements Runnable{
	
	BlockingQueue<Cargo> mailbox;
	int active_port;
	int pasive_port;
	SharedBoolean active;
	int monitor_port;
	
	private final int BUFFER_SIZE = 1024*1024; 
	private final int TRYS = 3;
	
	public IncomingHandler(int ap, int pp, int mp, BlockingQueue<Cargo> queue, SharedBoolean a)
	{
		mailbox = queue;
		active_port = ap;
		pasive_port = pp;
		active = a;
		monitor_port = mp;
	}
	
	public void run()
	{
		while (true)
		{
			if (active.value())
			{
				System.out.print("Active mode initiated.\n");
				DatagramSocket sock = null;
				int trys = 0;
				
				while (sock == null)
				{
					try
					{
						sock = new DatagramSocket(active_port);
					}
					catch(Exception e)
					{ 
						if (e.getMessage().equals("Address already in use") && trys < TRYS)
						{
							trys++;
							try{
								Thread.sleep(2000);
							}catch(Exception ex){ System.out.print("FATAL ERROR. Can't sleep IncomingHandler: " + ex.getMessage() + "\n"); System.exit(666); }
						}
						else
						{
							System.out.print("FATAL ERROR. Error opening active port: " + e.getMessage() + "\n"); 
							System.exit(666); 
						}
					}
				}
				
				System.out.print("Active port opened.\n");
				byte[] buffer = new byte[BUFFER_SIZE];
				DatagramPacket packet = new DatagramPacket(buffer, BUFFER_SIZE); 
				
				while (true)
				{
					try{
						sock.receive(packet);
					}catch(Exception e){ System.out.print("Error reciving packet on active: " + e.getMessage() + "\n"); continue; }
					System.out.println("Packet recived on active: " + new String(buffer, 0, packet.getLength()) + "\n");
					
					try{
						mailbox.put(new Cargo(new String(buffer, 0, packet.getLength()), Sender.toString(packet.getAddress())));
					}catch(Exception e){ System.out.print("Error submitting packet to handler: " + e.getMessage() + "\n");}
					
					packet.setLength(BUFFER_SIZE);
				}
			}
			else
			{
				System.out.print("Pasive mode initiated.\n");
				DatagramSocket sock = null;
				int trys = 0;

				while (sock == null)
				{
					try
					{
						sock = new DatagramSocket(pasive_port);
					}
					catch(Exception e)
					{
						if (e.getMessage().equals("Address already in use") && trys < TRYS)
						{
							trys++;
							try{
								Thread.sleep(2000);
							}catch(Exception ex){ System.out.print("FATAL ERROR. Can't sleep IncomingHandler: " + ex.getMessage() + "\n"); System.exit(666); }
						}
						else
						{
							System.out.print("FATAL ERROR. Error opening pasive port: " + e.getMessage() + "\n");
							System.exit(666);
						}
					}
				}
				
				System.out.print("Pasive port opened.\n");
				byte[] buffer = new byte[BUFFER_SIZE];
				DatagramPacket packet = new DatagramPacket(buffer, BUFFER_SIZE); 

				while (!active.value())
				{
					try{
						sock.receive(packet);
					}catch(Exception e){ System.out.print("Error reciving packet on pasive: " + e.getMessage() + "\n"); continue; }
					String msg = new String(buffer, 0, packet.getLength());
					System.out.println("Packet recived on pasive: " + msg + "\n");
						
					JSONObject detail = null;
					try{
						detail = new JSONObject(msg);
					}catch(Exception e){ System.out.print("Error parsing recived message on pasive: " + e.getMessage() + "\n"); }
					
					try{
						System.out.print("Packet type: " + detail.getString("type") + "\n");
						if (detail.getString("type").equals("PING"))
							Sender.ok("localhost", monitor_port, detail.getInt("id"));
						
						if (detail.getString("type").equals("ACTIVATE"))
							active.set(true);
					}catch(Exception e){ System.out.print("Error decoding message format: " + e.getMessage() + "\n"); }
					
					packet.setLength(BUFFER_SIZE);
			}
			}
		}
	}

//	public void run()
//	{
//		try {
//			
//			while (true)
//			{
//				if (active)
//				{
//					System.out.print("Entrando en modo activo\n");
//					ServerSocket sock = new ServerSocket(active_port);
//					
//					while (true)
//					{
//						Socket conection = sock.accept();
//						System.out.println("Recibiendo paquete\n");
//						
//						BufferedReader inFromClient = new BufferedReader(new InputStreamReader(conection.getInputStream()));
//						
//						mailbox.put(new Cargo(inFromClient.readLine(), conection.getInetAddress().toString()));
//						
//						conection.close();
//						inFromClient.close();
//					}
//				}
//				else
//				{
//					System.out.print("Entrando en modo pasivo\n");
//					ServerSocket sock = new ServerSocket(pasive_port);
//
//					while (!active)
//					{
//						Socket conection = sock.accept();
//						System.out.println("EN PASIVO: Recibiendo paquete\n");
//
//						BufferedReader inFromClient = new BufferedReader(new InputStreamReader(conection.getInputStream()));
//						String msg = inFromClient.readLine();
//						JSONObject detail = new JSONObject(msg);
//						
//						if (detail.getString("type").equals("PING"))
//							Sender.ok("localhost", monitor_port, detail.getInt("id"));
//						
//						if (detail.getString("type").equals("ACTIVATE"))
//							active = true;
//						
//						conection.close();
//						inFromClient.close();
//					}
//				}
//			}
//		} catch (Exception  e) {
//			System.out.println("Error on Incoming Handler\n");
//		}		
//	}

}
